package com.chaoxin.lovehelp.service.impl;

import com.alibaba.dashscope.app.*;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.druid.util.StringUtils;
import com.chaoxin.lovehelp.common.enums.ErrorCode;
import com.chaoxin.lovehelp.common.enums.SystemEnum;
import com.chaoxin.lovehelp.common.exception.BusinessException;
import com.chaoxin.lovehelp.common.utils.R;
import com.chaoxin.lovehelp.common.utils.RedisHelper;
import com.chaoxin.lovehelp.entity.FellowEntity;
import io.reactivex.Flowable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class AiService {

    private final String api_key = "sk-ddc7e596cdb541e9904eb3a4c4ea191f";
    private final String app_id = "f6f5eb362fce4fd7b29f84ccdfca33c4";

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public void streamChat(HttpServletRequest request,
                           String userMessage,
                           ResponseBodyEmitter emitter)
            throws NoApiKeyException, InputRequiredException {

        // 1. 从 Session 获取用户信息
        FellowEntity loginUser = (FellowEntity) request.getSession()
                .getAttribute(SystemEnum.LOGIN_STATUS.getName());
        Integer userId = loginUser.getId();

        // 2. 构造流式调用参数
        ApplicationParam param = ApplicationParam.builder()
                .apiKey(api_key)
                .appId(app_id)
                .prompt(userMessage)
                .incrementalOutput(true)    // 开启增量流式输出
                .build();

        // 4. 调用流式接口
        Application application = new Application();
        Flowable<ApplicationResult> stream = application.streamCall(param);

        // 5. 逐片段推送给前端，并累积完整内容
        StringBuilder fullContent = new StringBuilder();
        final String[] sessionId= new String[1];
        stream.blockingForEach(result -> {
            if (result.getOutput().getSessionId() != null) {
                sessionId[0] = result.getOutput().getSessionId();

            }
            String delta = result.getOutput().getText();
            fullContent.append(delta);
            System.out.println("数据片段"+delta);
            try {
                emitter.send(delta);    // SSE 推送当前片段
            } catch (IOException e) {
                // 出现 IO 错误时中断流
                emitter.completeWithError(e);
                throw new RuntimeException(e);
            }
        });
        System.out.println("AI 回复完整记录"+fullContent.toString());
        //5先保存用户提问
        saveChatRecord(userId, sessionId[0], "User", userMessage);
        // 6. 流结束后保存 AI 回复完整记录
        saveChatRecord(userId, sessionId[0], "AI", fullContent.toString());
    }

    // 处理用户消息
    /**
     * 将 SDK 的 Flowable 流式结果，通过 SseEmitter 一条条 send() 给前端
     */
    public void streamChat(HttpServletRequest request,
                           String userMessage,
                           String sessionId,
                           ResponseBodyEmitter emitter)
            throws NoApiKeyException, InputRequiredException {

        // 1. 从 Session 获取用户信息
        FellowEntity loginUser = (FellowEntity) request.getSession()
                .getAttribute(SystemEnum.LOGIN_STATUS.getName());
        Integer userId = loginUser.getId();

        // 2. 构造流式调用参数
        ApplicationParam param = ApplicationParam.builder()
                .apiKey(api_key)
                .appId(app_id)
                .prompt(userMessage)
                .sessionId(sessionId)
                .incrementalOutput(true)    // 开启增量流式输出
                .build();

        // 3. 先保存用户提问
        saveChatRecord(userId, sessionId, "User", userMessage);

        // 4. 调用流式接口
        Application application = new Application();
        Flowable<ApplicationResult> stream = application.streamCall(param);

        // 5. 逐片段推送给前端，并累积完整内容
        StringBuilder fullContent = new StringBuilder();
        stream.blockingForEach(result -> {
            String delta = result.getOutput().getText();
            fullContent.append(delta);
            System.out.println("数据片段"+delta);
            try {
                emitter.send(delta);    // SSE 推送当前片段
            } catch (IOException e) {
                // 出现 IO 错误时中断流
                emitter.completeWithError(e);
                throw new RuntimeException(e);
            }
        });
        System.out.println("AI 回复完整记录"+fullContent.toString());
        // 6. 流结束后保存 AI 回复完整记录
        saveChatRecord(userId, sessionId, "AI", fullContent.toString());
    }


    //新会话

//    public HashMap requestAi(HttpServletRequest request, String userMessage) throws NoApiKeyException, InputRequiredException {
//        FellowEntity loginUser =(FellowEntity) request.getSession().getAttribute(SystemEnum.LOGIN_STATUS.getName());
//        ApplicationParam param = ApplicationParam.builder()
//                .apiKey(api_key)
//                .appId(app_id)
//                .prompt(userMessage)
//                .build();
//        Integer userId=loginUser.getId();
//
//        Application application = new Application();
//        ApplicationResult result = application.call(param);
//        String aiResponse = result.getOutput().getText();
//        String newSessionId = result.getOutput().getSessionId();
//        saveChatRecord(userId, newSessionId, "User", userMessage);
//        saveChatRecord(userId,newSessionId, "AI", aiResponse);
//        HashMap<Object, Object> r = new HashMap<>();
//        r.put("aiResponse",aiResponse);
//        r.put("sessionId",newSessionId);
//        return r;
//    }
    // 保存聊天记录到 Redis
    private void saveChatRecord(Integer userId, String sessionId, String role, String message) {
        String key = "chat:" + userId + ":" + sessionId;
        Map<String, Object> record = new HashMap<>();
        record.put("role",  role);
        record.put("message",  message);
        record.put("timestamp",  System.currentTimeMillis());
        redisTemplate.opsForList().rightPush(key,  record);
        redisTemplate.expire(key,  30, TimeUnit.DAYS); // 设置过期时间为 30 天
    }

    // 查询单一会话聊天记录
    public R getChatRecords(HttpServletRequest request, String sessionId) {
        FellowEntity loginUser =(FellowEntity) request.getSession().getAttribute(SystemEnum.LOGIN_STATUS.getName());
        String key = "chat:" + loginUser.getId() + ":" + sessionId;
        List<Object> rawRecords = redisTemplate.opsForList().range(key,  0, -1);

        if (rawRecords == null || rawRecords.isEmpty())  {
            throw  new BusinessException(ErrorCode.PARAMS_ERROR,"该会话不存在");
        }

        // Get the first user message as title
        String title = "";
        for (Object record : rawRecords) {
            if (record instanceof Map) {
                Map<String, Object> r = (Map<String, Object>) record;
                if ("User".equals(r.get("role")))  {
                    title = (String) r.get("message");
                    break;
                }
            }
        }

        // Format the messages
        List<Map<String, Object>> messages = new ArrayList<>();
        for (Object record : rawRecords) {
            if (record instanceof Map) {
                Map<String, Object> r = (Map<String, Object>) record;
                Map<String, Object> message = new HashMap<>();
                if ("User".equals(r.get("role")))  {
                    message.put("user",  r.get("message"));
                    message.put("user_timestamp",  r.get("timestamp"));
                } else {
                    message.put("ai",  r.get("message"));
                    message.put("ai_timestamp",  r.get("timestamp"));
                }
                messages.add(message);
            }
        }

        Map<String, Object> result = new HashMap<>();
        result.put("session_id",  sessionId);
        result.put("title",  title);
        result.put("messages",  messages);
        return R.ok().setData(result);
    }

    /**
     * 获取用户的历史会话列表（只包含sessionId和首条消息作为标题）
     * @param userId 用户ID
     * @return 会话列表，每个会话包含session_id和title
     */
    public List<Map<String, String>> getUserSessionList(Long userId) {
        // 构造匹配所有该用户会话的key模式
        String pattern = "chat:" + userId + ":*";

        // 使用RedisHelper的scan方法查找所有匹配的key
        Set<String> keys = RedisHelper.scan(redisTemplate,  pattern);

        List<Map<String, String>> sessionList = new ArrayList<>();

        for (String key : keys) {
            // 从key中提取sessionId (格式为 "chat:userId:sessionId")
            String sessionId = key.split(":")[2];

            // 获取该会话的第一个用户消息作为标题
            List<String> E= getSessionTitle(key);

            Map<String, String> sessionInfo = new HashMap<>();
            sessionInfo.put("session_id",  sessionId);
            sessionInfo.put("title",(String) E.get(0));
            //最后一条作为时间
            List<String> E1= getSessionTime(key);
            sessionInfo.put("start_timestamp",(String) E1.get(0));
            sessionList.add(sessionInfo);
        }
        // 按照时间戳从最新到最旧排序
        sessionList.sort((map1,  map2) -> {
            String time1 = map1.get("start_timestamp");
            String time2 = map2.get("start_timestamp");
            // 假设时间戳是字符串格式的，可以直接比较
            // 如果是数字时间戳，可以转换为Long进行比较
            return time2.compareTo(time1);  // 降序排列
        });

        return sessionList;
    }

    /**
     * 从Redis中获取会话的标题（第一条用户消息）
     * @param key Redis key
     * @return 标题（第一条用户消息或默认值）
     */
    private List<String> getSessionTitle(String key) {
        // 获取会话的所有记录
        List<Object> records = redisTemplate.opsForList().range(key,  0, -1);


        List<String> result = new ArrayList<>();
        // 查找第一条用户消息
        for (Object record : records) {
            if (record instanceof Map) {
                Map<String, Object> r = (Map<String, Object>) record;
                if ("User".equals(r.get("role")))  {
                    result.add((String) r.get("message"));
//                    result.add(r.get("timestamp").toString());
                    break;
                }
            }
        }
        return result;
    }

    /**
     * 从Redis中获取会话最后一条时间戳
     * @param key Redis key
     * @return 时间戳map
     */
    private List<String> getSessionTime(String key) {
        // 获取一个会话的所有记录
        List<Object> records = redisTemplate.opsForList().range(key,  0, -1);


        List<String> result = new ArrayList<>();
        //查找最后一条消息
        if(records.size()>0){
            Map<String, Object> r = (Map<String, Object>) records.get(records.size()-1);
            result.add((String) r.get("timestamp").toString());
        }
        return result;
    }
    // 删除单一会话聊天记录
    public R deleteChatRecords(HttpServletRequest request, String sessionId) {
        FellowEntity loginUser = (FellowEntity) request.getSession().getAttribute(SystemEnum.LOGIN_STATUS.getName());
        String key = "chat:" + loginUser.getId() + ":" + sessionId;
        Boolean deleted = redisTemplate.delete(key);
        if (deleted) {
            return R.ok().setData("会话记录删除成功");
        } else {
            return R.error().setData("会话记录删除失败或会话不存在");
        }
    }
    // 删除用户所有聊天会话记录
    public R deleteAllUserChatRecords(Long userId) {
        String pattern = "chat:" + userId + ":*";
        Set<String> keys = RedisHelper.scan(redisTemplate, pattern);
        if (!keys.isEmpty()) {
            redisTemplate.delete(keys);
            return R.ok().setData("用户所有聊天会话记录删除成功");
        } else {
            return R.error().setData("用户没有聊天会话记录");
        }
    }
}
